/**
 * Magic webapp.js 1.0.2
 * Author: Mac_J@boarsoft.com
 */
var Cache = {};
var App = {
	schemes: {
		basic: {}
	},
	//a：操作内容， d：返回的消息编码，m：消息模板
	error: function(a, d, m){
		var s = mac.eval('Msg.' + d);
		if (d == 'error.needLogin' || d == 'error.logonTimeout') {
			alert(s);
			window.location.href = App.ctx + '/login.htm';
		} else {
			mac.alert(m || Msg.info.error, [ a, s ]);
		}
	},
	init : function(aa, pg) {
		pg.loading = aa.length;
		mac.loader(pg);
		$.each(aa, function(i, a) {
			$.post(a.url, a.params, function(rs) {
				a.callback(mac.eval(rs));
				pg.loading--;
				if (pg.loading==0 && pg.init) {
					pg.init();
				}
			});
		});
	},
	open: function(c, cb, al) {
		var x = App[c.ctx];
		if (!x) {
			alert('Context ' + c.ctx + '/' + c.action + ' is not exists');
			return;
		}
		var d = x[c.action];
		if (!d) {
			alert('Action ' + c.ctx + '/' + c.action + ' is not exists');
			return;
		}
		var v = App.schemes[App.scheme];
		if (!v) {
			alert('Scheme ' + App.scheme + ' is not exists');
			return;
		}
		v = v[c.ctx];
		if (!v) {
			alert('Scheme ' + App.scheme + '/' + c.ctx + ' is not exists');
			return;
		}
		v = v[c.action];
		if (!v) {
			alert('Scheme ' + App.scheme + '/' + c.ctx + '/' + c.action + ' is not exists');
			return;
		}
		var a = $('<div class="window ' + c.action + '"></div>');
		a.callback = cb;
		a.params = c.params;
		a.mac('dialog', {
			title : c.title || d.title || '',
			width : c.width || v.width,
			height : c.height || v.height,
			minWidth : c.width || v.minWidth,
			minHeight : c.height || v.minHeight,
			position : v.position,
			resizable : v.resizable,
			model : (c.model==undefined? v.model:c.model),
			autoOpen : true,
			onClose : c.onClose,
			noCloser : c.noCloser,
			closeAction: c.closeAction || d.closeAction || 'remove',
			draggable: true,
			closeOnEsc: (c.closeOnEscape==undefined? d.closeOnEscape:c.closeOnEscape)
		});
		d.ui = a;
		if (c.rpath) {
			d.rpath = c.rpath;
			d.ui.load(c.rpath + d.url, null, al);
		} else if (c.el) {
			d.ui.body.append(c.el);
		} else {
			d.rpath = '';
			d.ui.body.load(d.url, null, al);
		}
		return a;
	},
	popup : function(d, g) {
		var c = d.action, e = App[c]
			, f = App.viewSet[c] || {};
		$.extend(f, d);
		var b = $("<div></div>").mac("dialog", f);
		if (g) {
			b.callback = g;
		}
		if (d.params) {
			b.params = d.params;
		}
		e.ui = b;
		var a = mac.wait(Msg.info.loading);
		e.rpath = d.rpath ? d.rpath : "";
		b.load(e.rpath + e.url, function() {
			b.show();
			a.close();
		});
		return b;
	},
	show : function(pa, uc, pe, al) {
		var pe = pe || App.main.css("height", "")
			, xt = App[pa.ctx];
		if (!xt) {
			alert('Context ' + pa.ctx + '/' + pa.action + ' is not exists');
			return;
		}
		var mo = xt[pa.action];
		if (!mo) {
			alert('Action ' + pa.ctx + '/' + pa.action + ' is not exists');
			return;
		}
		mo.ui = $('<div class="' + (pa.id || pa.action) + '"></div>');
		if (App.timer) {
			window.clearInterval(App.timer);
		}
		pe.empty().append(mo.ui);
		//if (pa.params || mo.params) {
		//	mo.ui.params = $.extend(pa.params || {}, mo.params || {});
		//}
		mo.ui.params = pa.params;
		var w = mac.wait(Msg.loading);
		var uu = mo.ui;
		mo.ui.load(mo.url, function(a) {
			// window.location.hash = pa.action;
			w.close();
			if (pe.afterLoad)
				pe.afterLoad();
			if (al)
				al(mo.ui);
		});
		mo.ui.callback = uc;
		return mo.ui;
	},
	getQueryParam: function(k) {
		var r = new RegExp("(^|&)" + k + "=([^&]*)(&|$)", "i")
			, s = window.location.search.substr(1).match(r);
		return (s != null ? unescape(s[2]): null);
	},
	getHashParam: function(k) {
		var r = new RegExp("(^|&)" + k + "=([^&]*)(&|$)", "i")
			, h = window.location.hash, s = h.substr(h.indexOf('?') + 1).match(r);
		return (s != null ? unescape(s[2]): null);
	},
	websocket: {
		listeners: {},
		open: function(la){
			var me = this, la = la || {};
			if (me.url) {
				$.extend(me.listeners, la);
				return me;
			}
			var wl = window.location,
				url = me.url = 'ws://' + wl.host + wl.pathname + 'websocket',
				ws = me.ws = new WebSocket(url);
			me.listeners = la;
			console.info('Connect websocket ' + url);
			
			ws.onopen = function (e){
				ws.send("{ token: '" + App.logon.token + "', type: 0, group: 'init' }");
				var fa = la.onopen || [];
				for (var i in fa) {
					fa[i](e, ws);
				}
			};
			ws.onclose = function (e){
				var fa = la.onclose || [];
				for (var i in fa) {
					fa[i](e, ws);
				}
				ws = null;
			};
			ws.onerror = function (e) {
				var fa = la.onerror || [];
				for (var i in fa) {
					fa[i](e, ws);
				}
				try {
					ws.close();
				} catch (x) {
					console.error(x);
				} finally {
					ws = null;
					console.error(e);
				}
			};
			ws.onmessage = function (e){
				console.info('Incoming websocket message: ' + e.data);
				try {
					var o = mac.eval(e.data), g = la[o.group];
					if (g) {
						var c = g[o.code];
						for (var k in c) {
							var f = c[k];
							try {
								f(o, e, ws);
							} catch (e) {
								console.error(e);
								console.info('Remove invalid listener '
									+ o.group + '/' + o.code + '/' + k);
								delete c[k];
							}
						}
						return;
					}
					console.warn('Unknown websocket message: ' + e.data);
				} catch (x) {
					console.error(x);
				}
			};
		},
		on: function(g, c, k, f){
			var ga = this.listeners, ca = ga[g];
			if (!ca) {
				ga[g] = ca = {};
			}
			var fa = ca[c];
			if (!fa) {
				ca[c] = fa = {};
			}
			fa[k] = f;
		},
		off: function(g, c, k){
			var ca = this.listeners[g] || {};
			console.info('delete websocket listener: ' + g + '/' + c + '/' + k);
			delete (ca[c] || {})[k];
		}
	}
}
// -------------
Number.prototype.to3ps = function(d) {
	d = d || 0;
	var s = String(this.toFixed(d));
	var g = /(\d{1,3})(?=(\d{3})+$)/g;
	if (d < 1)
		return s.replace(g, "$1,");
	var i = s.length - d;
	var p = s.substr(0, i - 1);
	var x = s.substr(i);
	p = p.replace(g, "$1,");
	return p + '.' + x;
}
Date.prototype.format = function(fmt) {
	var o = {
		"M+" : this.getMonth() + 1, // 月份
		"d+" : this.getDate(), // 日
		"h+" : this.getHours() % 12 == 0 ? 12 : this.getHours() % 12, // 小时
		"H+" : this.getHours(), // 小时
		"m+" : this.getMinutes(), // 分
		"s+" : this.getSeconds(), // 秒
		"q+" : Math.floor((this.getMonth() + 3) / 3), // 季度
		"S" : this.getMilliseconds()
	// 毫秒
	};
	if (/(y+)/.test(fmt)) {
		fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "")
				.substr(4 - RegExp.$1.length));
	}
	if (/(E+)/.test(fmt)) {
		// fmt = fmt.replace(RegExp.$1, ((RegExp.$1.length > 1) ?
		// (RegExp.$1.length > 2 ? "星期" : "周") : "") + week[this.getDay() +
		// ""]);
		var r = RegExp.$1, w = Msg.datepicker, d = this.getDay();
		fmt = fmt.replace(r, r.length > 1 ? (r.length > 2 ? w.dayNames[d]
				: w.dayNamesShort[d]) : '');
	}
	for ( var k in o) {
		if (new RegExp("(" + k + ")").test(fmt)) {
			fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k])
					: (("00" + o[k]).substr(("" + o[k]).length)));
		}
	}
	return fmt;
}
String.prototype.len=function() {
	return this.replace(/[^\x00-\xff]/g,"rr").length;
}
String.prototype.sub = function(n) {
	var r = /[^\x00-\xff]/g;
	if (this.replace(r, "mm").length <= n)
		return this;
	var m = Math.floor(n / 2);
	for (var i = m; i < this.length; i++) {
		if (this.substr(0, i).replace(r, "mm").length >= n) {
			return this.substr(0, i);
		}
	}
	return this;
}
String.prototype.gblen = function() {
	var len = 0;
	for (var i = 0; i < this.length; i++) {
		if (this.charCodeAt(i) > 127 || this.charCodeAt(i) == 94) {
			len += 2;
		} else {
			len++;
		}
	}
	return len;
}